import path from 'path';
import { promises as fs } from 'fs';
import { FileSystem } from './fileSystem';
import { IEncryptor, ISerializer } from '../types';

/**
 * 备份工具类
 */
export class Backup {
    /** 备份目录名 */
    private static readonly BACKUP_DIR = 'backups';
    
    /** 最大备份数量 */
    private static readonly MAX_BACKUPS = 5;

    /**
     * 创建备份
     * @param filePath 文件路径
     * @param encryptor 加密器（可选）
     * @param serializer 序列化器（可选）
     */
    static async create(filePath: string, encryptor?: IEncryptor, serializer?: ISerializer): Promise<string> {
        const backupDir = path.join(path.dirname(filePath), this.BACKUP_DIR);
        await FileSystem.ensureDir(backupDir);

        // 生成备份文件名
        const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
        const fileName = path.basename(filePath);
        const backupPath = path.join(backupDir, `${fileName}.${timestamp}.bak`);

        try {
            // 读取原文件
            if (await FileSystem.exists(filePath)) {
                const content = await FileSystem.readFile(filePath, encryptor);
                
                // 如果提供了序列化器，尝试验证数据格式
                if (serializer) {
                    try {
                        const data = serializer.deserialize(content);
                        const reserializedContent = serializer.serialize(data);
                        await FileSystem.writeFile(backupPath, reserializedContent, encryptor);
                    } catch {
                        // 如果序列化失败，直接复制原内容
                        await FileSystem.writeFile(backupPath, content, encryptor);
                    }
                } else {
                    // 直接复制原内容
                    await FileSystem.writeFile(backupPath, content, encryptor);
                }
            }

            // 清理旧备份
            await this.cleanup(backupDir, fileName);

            return backupPath;
        } catch (error) {
            throw new Error(`Failed to create backup: ${(error as Error).message}`);
        }
    }

    /**
     * 从备份恢复
     * @param filePath 目标文件路径
     * @param backupPath 备份文件路径
     * @param encryptor 加密器（可选）
     */
    static async restore(filePath: string, backupPath: string, encryptor?: IEncryptor): Promise<void> {
        try {
            if (!await FileSystem.exists(backupPath)) {
                throw new Error(`Backup file not found: ${backupPath}`);
            }

            const content = await FileSystem.readFile(backupPath, encryptor);
            await FileSystem.writeFile(filePath, content, encryptor);
        } catch (error) {
            throw new Error(`Failed to restore from backup: ${(error as Error).message}`);
        }
    }

    /**
     * 获取最新的备份
     * @param filePath 文件路径
     */
    static async getLatestBackup(filePath: string): Promise<string | null> {
        const backupDir = path.join(path.dirname(filePath), this.BACKUP_DIR);
        const fileName = path.basename(filePath);

        try {
            if (!await FileSystem.exists(backupDir)) {
                return null;
            }

            const files = await fs.readdir(backupDir);
            const backups = files
                .filter(f => f.startsWith(`${fileName}.`) && f.endsWith('.bak'))
                .sort()
                .reverse();

            return backups.length > 0 ? path.join(backupDir, backups[0]) : null;
        } catch {
            return null;
        }
    }

    /**
     * 清理旧备份
     * @param backupDir 备份目录
     * @param fileName 文件名
     */
    private static async cleanup(backupDir: string, fileName: string): Promise<void> {
        try {
            const files = await fs.readdir(backupDir);
            const backups = files
                .filter(f => f.startsWith(`${fileName}.`) && f.endsWith('.bak'))
                .sort()
                .reverse();

            // 删除超出数量限制的旧备份
            for (let i = this.MAX_BACKUPS; i < backups.length; i++) {
                await fs.unlink(path.join(backupDir, backups[i]));
            }
        } catch {
            // 忽略清理错误
        }
    }
}
